//receptor asincrono con protocolo RS232

module uart_p(clk_50M,arst,rxd,txd,LCD,SF_D,rxd_o,par_error);
  
  input  clk_50M,arst;
  input  rxd;
  
  output  reg txd = 0;
  
  reg     [7:0]txd_alm;
  wire    [7:0]txd_;
  output  reg [7:0]rxd_o;
  output  reg [7:0]par_error=0;
  reg     pari;
  reg    [9:0]rxd_reg;
  reg    [4:0]cont=0;
  reg    bit=0;
 
  reg    [20:0]sin = 0;
  reg    c=0;
  reg    [3:0]sabe=0;
  reg    q1;
  reg    q2;
  
  reg    trans;
  reg    [1:0]datos=0;  
  wire   [31:0]d_in_u;
  
  output reg     [3:0]SF_D; 
  output reg     [2:0]LCD; 
    
  reg        [19:0]count=0; 
  reg        [5:0]Bit = 0;
  parameter  [1:0]let = 2'b10; 
  parameter   s0 = 6'b00_0000,
              s1 = 6'b00_0001,
              s2 = 6'b00_0010,
              s3 = 6'b00_0011,
              s4 = 6'b00_0100,
              s5 = 6'b00_0101,
              s6 = 6'b00_0110,
              s7 = 6'b00_0111,
              s8 = 6'b00_1000,
              s9 = 6'b00_1001,
              s10= 6'b00_1010,
              s11= 6'b00_1011,
              s12= 6'b00_1100,
              s13= 6'b00_1101;
              
  
  
  parameter staby = 5'b00000,
            start = 5'b00001,
            b1    = 5'b00010,
            b2    = 5'b00011,
            b3    = 5'b00100,
            b4    = 5'b00101,
            b5    = 5'b00110,
            b6    = 5'b00111,
            b7    = 5'b01000,
            b8    = 5'b01001,
            par   = 5'b01010,
            sto   = 5'b01011,
           startT = 5'b01100,
            t1    = 5'b01101,
            t2    = 5'b01110,
            t3    = 5'b01111,
            t4    = 5'b10000,
            t5    = 5'b10001,
            t6    = 5'b10010,
            t7    = 5'b10011,
            t8    = 5'b10100,
            parT   =5'b10101,
            stoT   =5'b10110;
  
  reg [4:0]cur_state = staby;
                
 always @ (posedge clk_50M)
 begin
   sin <= sin + 1;
   if (sin == 651)
     begin
     c <= ~c;
     sin <= 0;
   end
end

always @ (posedge c)begin
  q1 <= rxd;
  q2 <= q1; 
     
   case(cur_state)
     staby: begin
       if (datos == 3)begin
         trans <= 1;
         datos <= 0;
         cur_state <= startT;
       end
       if(rxd == 0)
         cur_state <= start;
      
       end
            
         start : begin
           if((sabe == 4'b0000) && (q2 == 0))
             begin
               cur_state <= b1;
             end
           end          
         
         b1: begin
           sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[0] <= q2;
               cur_state <=b2;
             end
           end
           
         b2:begin
           sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[1] <= q2;
               cur_state <= b3;            
             end
           end
           
           b3:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[2] <= q2;
               cur_state <=b4;     
             end
           end
           
           b4:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[3] <= q2;
               cur_state <=b5;     
             end
           end
           
           b5:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[4] <= q2;
               cur_state <=b6;     
             end
           end
           
           b6:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[5] <= q2;
               cur_state <=b7;     
             end
           end
           
           b7:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[6] <= q2;
               cur_state <=b8;     
             end
           end
           
           b8:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[7] <= q2;
               cur_state <=par;     
             end         
           end
           
           par:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[8] <= q2;
               cur_state <=sto;     
             end
           end
           
           sto:begin
             sabe <= sabe + 1;
           if(sabe == 4'b0011)
             begin
               sabe <= 0;
               rxd_reg[9] <= q2;
               pari <= ^rxd_reg[7:0];
               bit <= 1;
               cur_state<=staby;
             end
           end
           
           startT : begin
           if (trans)
             begin
              txd_alm <= (txd_ + 6'b11_0000);
              trans <=0;
              txd <= 0;
               cur_state <= t1;
             end
           end          
         
         t1: begin
           cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= txd_alm[0];
               cur_state <=t2;
             end
           end
           
         t2:begin
           cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               txd <= txd_alm[1];
               cont <= 0;
               cur_state <= t3;            
             end
           end
           
           t3:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= txd_alm[2];
               cur_state <=t4;     
             end
           end
           
           t4:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= txd_alm[3];
               cur_state <=t5;     
             end
           end
           
           t5:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= txd_alm[4];
               cur_state <=t6;     
             end
           end
           
           t6:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <=txd_alm[5];
               cur_state <=t7;     
             end
           end
           
           t7:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= txd_alm[6];
               cur_state <=t8;     
             end
           end
           
           t8:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <=txd_alm[7];
               cur_state <=parT;     
             end         
           end
           
           parT:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= ^txd_alm;
               cur_state <=stoT;     
             end
           end
           
           stoT:begin
             cont <= cont + 1;
           if(cont == 4'b0011)
             begin
               cont <= 0;
               txd <= 1;
               cur_state<= staby;           
             end
           end 
        endcase
    
        if (bit)
          begin
            if(pari == rxd_reg[8])
              par_error <= 0;
            else
              par_error <= 8'b11111111;
            if ((par_error == 8'b00000000) && (rxd_reg[9] == 1))
              begin
              datos <= datos + 1;
              rxd_o <= rxd_reg;
              bit <= 0;  
              end
          end 
      end
          
  
  always @ (posedge clk_50M) begin
  count <= count + 1;
  if (count == 20'b1011_0111_0001_1011_0000)
    begin
      Bit <= Bit + 1;
      count <= 0;
    end
    
  case (Bit) 
       s0: {LCD[1:0],SF_D[3:0]} <= 6'b00_0011;        // power-on initialization {LCD[1:0],SF_D[3:0]}
       s1: {LCD[1:0],SF_D[3:0]} <= 6'b00_0011; 
       s2: {LCD[1:0],SF_D[3:0]} <= 6'b00_0011; 
       s3: {LCD[1:0],SF_D[3:0]} <= 6'b00_0010; 
       s4: {LCD[1:0],SF_D[3:0]} <= 6'b00_0010;        // function set 
       s5: {LCD[1:0],SF_D[3:0]} <= 6'b00_1000; 
       s6: {LCD[1:0],SF_D[3:0]} <= 6'b00_0000;        // entry mode set 
       s7: {LCD[1:0],SF_D[3:0]} <= 6'b00_0110; 
       s8: {LCD[1:0],SF_D[3:0]} <= 6'b00_0000;        // display on/off control 
       s9: {LCD[1:0],SF_D[3:0]} <= 6'b00_1101; 
      s10: {LCD[1:0],SF_D[3:0]} <= 6'b00_0000;        // display clear 
      s11: {LCD[1:0],SF_D[3:0]} <= 6'b00_0001; 
      s12: {LCD[1:0],SF_D[3:0]} <= {let,rxd_o[7:4]};        // asignacion bits
      s13: {LCD[1:0],SF_D[3:0]} <= {let,rxd_o[3:0]}; 
      default: {LCD[1:0],SF_D[3:0]} <= 6'b01_0000; 
    endcase 
      LCD[2] <= ^count[19:18];  // ENABLE 
  end 
  
 
  Extencion extencion(.in(rxd_reg[7:0]),.d_ready(bit),.out(d_in_u));
  MIPS_32 mips (.clk(clk_50M),.arst(arst),.Din(d_in_u),.Dout(txd_));
    endmodule
      

      
      
  
  
  
  
